package com.xucia.jsponic.security;

import java.security.Permission;
import java.security.Principal;
import java.util.Set;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

public class UserSecurity {
	static SecurityHandler installedSecurity;
	public static User authenticate(final String username, final String password) throws LoginException {
		LoginContext loginContext;
		try {
			loginContext = new LoginContext("Jsponic", new CallbackHandler() {
				public void handle(Callback[] callbacks)
			    throws java.io.IOException, UnsupportedCallbackException {
			        for (int i = 0; i < callbacks.length; i++) {
			            if (callbacks[i] instanceof NameCallback) {
			                NameCallback nameCb = (NameCallback)callbacks[i]; 
			nameCb.setName(username);
			            } else if(callbacks[i] instanceof PasswordCallback) {
			                PasswordCallback passCb = (PasswordCallback)callbacks[i];
			                passCb.setPassword(password.toCharArray());
			            } else {
			                throw(new UnsupportedCallbackException(callbacks[i],
			                    "Callback class not supported"));
			             }
			        }
			    }
			});
		}
		catch (java.lang.SecurityException e) {
			// TODO: Handle any Principal
			User user = (User) installedSecurity.authenticate(username, password);
            user.registerThisThread();
            return user;
		}
		
		loginContext.login();
		Set<User> userObjectPrincipal = loginContext.getSubject().getPrincipals(User.class);
		if (!userObjectPrincipal.isEmpty())
			return userObjectPrincipal.iterator().next();
		for (Principal principal : loginContext.getSubject().getPrincipals()) {
			User user = User.getUserByUsername(principal.getName());
            user.registerThisThread();
			return user;
		}
		throw new LoginException("No principal was provided to get the user");
	}
	public static void main(String[] args) throws Exception {
		authenticate("test", "testpass");
	}
	public static java.security.acl.Group getSupervisorGroup() {
		return installedSecurity.getSupervisorGroup();
	}
	public static Principal getPublicUser() {
		return installedSecurity.getPublicUser();
	}
	public static Principal currentUser() {
		return User.currentUser();
	}
	public static boolean userHasPermission(Permission permission) {
		if (permission == JavaScriptCodingPermission.instance)
			return getSupervisorGroup().isMember(User.currentUser());
		return false;
	}
	public static SecurityHandler getInstalledSecurity() {
		return installedSecurity;
	}
	public static void setInstalledSecurity(SecurityHandler installedSecurity) {
		UserSecurity.installedSecurity = installedSecurity;
	}
}
